/**
 * @file analog_data.h
 * @brief 模拟数据模块 - 处理模拟量相关的所有数据类型
 * @details 本头文件定义了104协议中模拟量数据类型的结构体和操作函数，
 *          包括归一化值、标度化值、短浮点数、带时标的测量值、累计量等。
 *          支持完整的数据创建、转换和验证功能。
 * 
 * @author zyb
 * @date 2025-10-10
 * @version 1.0
 * 
 * @note 所有数据类型都遵循IEC 60870-5-104协议规范
 * @warning 数据转换时需要注意字节序和精度问题
 * 
 * @see protocol_types.h
 * @see error_codes.h
 * @see validation_utils.h
 */

#ifndef ANALOG_DATA_H
#define ANALOG_DATA_H

#include "../../common/types/include/protocol_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/* ==================== 模拟数据类型定义 ==================== */

/**
 * @brief 测量值-归一化值结构 (M_ME_NA_1)
 */
typedef struct {
    info_addr_t addr;       /* 信息对象地址 */
    s16 value;              /* 归一化值 */
    qds_t qds;              /* 品质描述词 */
} normalized_value_t;

/**
 * @brief 测量值-标度化值结构 (M_ME_NB_1)
 */
typedef struct {
    info_addr_t addr;       /* 信息对象地址 */
    s16 value;              /* 标度化值 */
    qds_t qds;              /* 品质描述词 */
} scaled_value_t;

/**
 * @brief 测量值-短浮点数结构 (M_ME_NC_1)
 */
typedef struct {
    info_addr_t addr;       /* 信息对象地址 */
    float value;            /* 短浮点数值 */
    qds_t qds;              /* 品质描述词 */
} short_float_value_t;

/**
 * @brief 带CP56Time2a时标的测量值-归一化值结构 (M_ME_TA_1)
 */
typedef struct {
    info_addr_t addr;       /* 信息对象地址 */
    s16 value;              /* 归一化值 */
    qds_t qds;              /* 品质描述词 */
    cp56time2a_t time;      /* 时间戳 */
} normalized_value_with_time_t;

/**
 * @brief 带CP56Time2a时标的测量值-标度化值结构 (M_ME_TB_1)
 */
typedef struct {
    info_addr_t addr;       /* 信息对象地址 */
    s16 value;              /* 标度化值 */
    qds_t qds;              /* 品质描述词 */
    cp56time2a_t time;      /* 时间戳 */
} scaled_value_with_time_t;

/**
 * @brief 带CP56Time2a时标的测量值-短浮点数结构 (M_ME_TC_1)
 */
typedef struct {
    info_addr_t addr;       /* 信息对象地址 */
    float value;            /* 短浮点数值 */
    qds_t qds;              /* 品质描述词 */
    cp56time2a_t time;      /* 时间戳 */
} short_float_value_with_time_t;

/**
 * @brief 累计量-短浮点数结构 (M_IT_NB_1)
 */
typedef struct {
    info_addr_t addr;       /* 信息对象地址 */
    float value;            /* 累计量值 */
    qds_t qds;              /* 品质描述词 */
} integrated_total_t;

/**
 * @brief 带CP56Time2a时标的累计量-短浮点数结构 (M_IT_TC_1)
 */
typedef struct {
    info_addr_t addr;       /* 信息对象地址 */
    float value;            /* 累计量值 */
    qds_t qds;              /* 品质描述词 */
    cp56time2a_t time;      /* 时间戳 */
} integrated_total_with_time_t;

/* ==================== 系统性能监控数据结构 ==================== */

/**
 * @brief GPU性能数据
 */
typedef struct {
    u8 temp;                /* GPU温度 */
    u8 fan;                 /* GPU风扇转速 */
    u8 power;               /* GPU功耗 */
    u8 usage;               /* GPU使用率 */
    u16 clock;              /* GPU时钟频率 */
    u8 mem;                 /* GPU显存使用率 */
    float volt;             /* GPU电压 */
    u8 fps;                 /* GPU帧率 */
} gpu_performance_t;

/**
 * @brief CPU性能数据
 */
typedef struct {
    u8 temp;                /* CPU温度 */
    u8 power;               /* CPU功耗 */
    u8 usage;               /* CPU使用率 */
    u16 clock;              /* CPU时钟频率 */
    u8 mem;                 /* CPU内存使用率 */
    float volt;             /* CPU电压 */
} cpu_performance_t;

/**
 * @brief RAM性能数据
 */
typedef struct {
    u8 usage;               /* RAM使用率 */
    u16 clock;              /* RAM时钟频率 */
    u8 mem;                 /* RAM内存使用率 */
    float volt;             /* RAM电压 */
} ram_performance_t;

/**
 * @brief 系统性能监控数据
 */
typedef struct {
    cp56time2a_t timestamp; /* 时间戳 */
    gpu_performance_t gpu;  /* GPU性能数据 */
    cpu_performance_t cpu;  /* CPU性能数据 */
    ram_performance_t ram;  /* RAM性能数据 */
    u8 overall_fps;         /* 整体帧率 */
} system_performance_t;

/* ==================== 模拟数据操作函数 ==================== */

/* ==================== 模拟数据转换函数 ==================== */

/**
 * @brief 归一化值转换为字节数组
 * @details 将归一化值结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化。
 * 
 * @param value 归一化值结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据序列化
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_normalized_value
 * @see validate_normalized_value
 */
protocol_error_t normalized_value_to_bytes(const normalized_value_t* value,
                                          u8* buffer, u32 buffer_size, u32* actual_length);

/**
 * @brief 字节数组转换为归一化值
 * @details 将104协议规定的字节数组格式转换为归一化值结构。
 *          按照协议规范进行数据反序列化。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param value 归一化值结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据反序列化
 * @warning 数据长度必须足够容纳归一化值
 * 
 * @see normalized_value_to_bytes
 * @see validate_normalized_value
 */
protocol_error_t bytes_to_normalized_value(const u8* data, u32 length,
                                          normalized_value_t* value);

/**
 * @brief 标度化值转换为字节数组
 * @details 将标度化值结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化。
 * 
 * @param value 标度化值结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据序列化
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_scaled_value
 * @see validate_scaled_value
 */
protocol_error_t scaled_value_to_bytes(const scaled_value_t* value,
                                      u8* buffer, u32 buffer_size, u32* actual_length);

/**
 * @brief 字节数组转换为标度化值
 * @details 将104协议规定的字节数组格式转换为标度化值结构。
 *          按照协议规范进行数据反序列化。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param value 标度化值结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据反序列化
 * @warning 数据长度必须足够容纳标度化值
 * 
 * @see scaled_value_to_bytes
 * @see validate_scaled_value
 */
protocol_error_t bytes_to_scaled_value(const u8* data, u32 length,
                                       scaled_value_t* value);

/**
 * @brief 短浮点值转换为字节数组
 * @details 将短浮点值结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化。
 * 
 * @param value 短浮点值结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据序列化
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_short_float_value
 * @see validate_short_float_value
 */
protocol_error_t short_float_value_to_bytes(const short_float_value_t* value,
                                           u8* buffer, u32 buffer_size, u32* actual_length);

/**
 * @brief 字节数组转换为短浮点值
 * @details 将104协议规定的字节数组格式转换为短浮点值结构。
 *          按照协议规范进行数据反序列化。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param value 短浮点值结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据反序列化
 * @warning 数据长度必须足够容纳短浮点值
 * 
 * @see short_float_value_to_bytes
 * @see validate_short_float_value
 */
protocol_error_t bytes_to_short_float_value(const u8* data, u32 length,
                                           short_float_value_t* value);

/**
 * @brief 带时标的归一化值转换为字节数组
 * @details 将带时标的归一化值结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化，包含时间戳。
 * 
 * @param value 带时标的归一化值结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 *         - PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP: 时间戳无效
 * 
 * @note 按照104协议规范进行数据序列化，包含时间戳
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_normalized_value_with_time
 * @see validate_normalized_value_with_time
 */
protocol_error_t normalized_value_with_time_to_bytes(const normalized_value_with_time_t* value,
                                                     u8* buffer, u32 buffer_size, u32* actual_length);

/**
 * @brief 字节数组转换为带时标的归一化值
 * @details 将104协议规定的字节数组格式转换为带时标的归一化值结构。
 *          按照协议规范进行数据反序列化，包含时间戳。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param value 带时标的归一化值结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 *         - PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP: 时间戳无效
 * 
 * @note 按照104协议规范进行数据反序列化，包含时间戳
 * @warning 数据长度必须足够容纳带时标的归一化值
 * 
 * @see normalized_value_with_time_to_bytes
 * @see validate_normalized_value_with_time
 */
protocol_error_t bytes_to_normalized_value_with_time(const u8* data, u32 length,
                                                     normalized_value_with_time_t* value);

/**
 * @brief 带时标的标度化值转换为字节数组
 * @details 将带时标的标度化值结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化，包含时间戳。
 * 
 * @param value 带时标的标度化值结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 *         - PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP: 时间戳无效
 * 
 * @note 按照104协议规范进行数据序列化，包含时间戳
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_scaled_value_with_time
 * @see validate_scaled_value_with_time
 */
protocol_error_t scaled_value_with_time_to_bytes(const scaled_value_with_time_t* value,
                                                 u8* buffer, u32 buffer_size, u32* actual_length);

/**
 * @brief 字节数组转换为带时标的标度化值
 * @details 将104协议规定的字节数组格式转换为带时标的标度化值结构。
 *          按照协议规范进行数据反序列化，包含时间戳。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param value 带时标的标度化值结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 *         - PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP: 时间戳无效
 * 
 * @note 按照104协议规范进行数据反序列化，包含时间戳
 * @warning 数据长度必须足够容纳带时标的标度化值
 * 
 * @see scaled_value_with_time_to_bytes
 * @see validate_scaled_value_with_time
 */
protocol_error_t bytes_to_scaled_value_with_time(const u8* data, u32 length,
                                                 scaled_value_with_time_t* value);

/**
 * @brief 带时标的短浮点值转换为字节数组
 * @details 将带时标的短浮点值结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化，包含时间戳。
 * 
 * @param value 带时标的短浮点值结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 *         - PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP: 时间戳无效
 * 
 * @note 按照104协议规范进行数据序列化，包含时间戳
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_short_float_value_with_time
 * @see validate_short_float_value_with_time
 */
protocol_error_t short_float_value_with_time_to_bytes(const short_float_value_with_time_t* value,
                                                      u8* buffer, u32 buffer_size, u32* actual_length);

/**
 * @brief 字节数组转换为带时标的短浮点值
 * @details 将104协议规定的字节数组格式转换为带时标的短浮点值结构。
 *          按照协议规范进行数据反序列化，包含时间戳。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param value 带时标的短浮点值结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 *         - PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP: 时间戳无效
 * 
 * @note 按照104协议规范进行数据反序列化，包含时间戳
 * @warning 数据长度必须足够容纳带时标的短浮点值
 * 
 * @see short_float_value_with_time_to_bytes
 * @see validate_short_float_value_with_time
 */
protocol_error_t bytes_to_short_float_value_with_time(const u8* data, u32 length,
                                                      short_float_value_with_time_t* value);

/**
 * @brief 累计量转换为字节数组
 * @details 将累计量结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化。
 * 
 * @param value 累计量结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据序列化
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_accumulated_value
 * @see validate_accumulated_value
 */
protocol_error_t accumulated_value_to_bytes(const measurement_info_t* value,
                                          u8* buffer, u32 buffer_size, u32* actual_length);

/**
 * @brief 字节数组转换为累计量
 * @details 将104协议规定的字节数组格式转换为累计量结构。
 *          按照协议规范进行数据反序列化。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param value 累计量结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据反序列化
 * @warning 数据长度必须足够容纳累计量
 * 
 * @see accumulated_value_to_bytes
 * @see validate_accumulated_value
 */
protocol_error_t bytes_to_accumulated_value(const u8* data, u32 length,
                                            measurement_info_t* value);

#ifdef __cplusplus
}
#endif

#endif /* ANALOG_DATA_H */
